package renhai.util.encrypt;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.*;
import java.security.Key;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * PBE加密算法
 *
 * @author rain
 */
public class PBEUtil {
    /**
     * 支持以下任意一种算法
     *
     * <pre>
     * PBEWithMD5AndDES
     * PBEWithMD5AndTripleDES
     * PBEWithSHA1AndDESede
     * PBEWithSHA1AndRC2_40
     * </pre>
     */
    public static final String ALGORITHM = "PBEWITHMD5andDES";

    /**
     * 盐初始化
     *
     * @return
     * @throws Exception
     */
    public static byte[] initSalt() {
        byte[] salt = new byte[8];
        SecureRandom random = new SecureRandom();
        random.nextBytes(salt);
        return salt;
    }

    /**
     * 转换密钥<br>
     *
     * @param password
     * @return
     * @throws Exception
     */
    private static Key toKey(String password) throws Exception {
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey secretKey = keyFactory.generateSecret(keySpec);

        return secretKey;
    }

    /**
     * 加密
     *
     * @param data     数据
     * @param password 密码
     * @param salt     盐
     * @return
     * @throws Exception
     */
    public static String encrypt(byte[] data, String password, byte[] salt) {

        try {
            Key key = toKey(password);
            PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            return encryptBASE64(cipher.doFinal(data));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 解密
     *
     * @param data     数据
     * @param password 密码
     * @param salt     盐
     * @return
     * @throws Exception
     */
    public static String decrypt(String data, String password, byte[] salt) {

        try {
            Key key = toKey(password);

            PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

            return new String(cipher.doFinal(decryptBASE64(data)));
        } catch (Exception e) {

        }
        return null;
    }

    public static void main(String[] args) throws Exception {
/*       String inputStr = "123123";
        System.err.println("原文: " + inputStr);  
        byte[] input = inputStr.getBytes();

        String pwd = "1214791733942960129";
        System.err.println("密码: " + pwd);

        byte[] salt = initSalt();
        SecureRandom random = new SecureRandom();
        System.out.println(byteArrayToLong(salt));

       String data ="EGFXNN36+N8=";

        System.err.println("加密后: " + data);
        Long i = 1937921924360029119L;
        String output = decrypt(data, pwd, varIntToByteArray(i));
        String outputStr = new String(output);  
        System.err.println("解密后: " + outputStr);

        System.out.println(Long.parseLong("6022176611977411836"));*/
        String fileName = "asadsd.123.zip";
        System.out.println(fileName.substring(fileName.lastIndexOf(".")));


    }

    public static long byteArrayToLong(byte[] bytes) {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        DataInputStream dis = new DataInputStream(bais);
        long result = 0;
        try {
            int len = dis.available();
            if (len == 1) {
                result = dis.readByte();
            } else if (len == 2) {
                result = dis.readShort();
            } else if (len == 4) {
                result = dis.readInt();
            } else if (len == 8) {
                result = dis.readLong();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                dis.close();
                bais.close();
            } catch (IOException e) {

            }
        }
        return result;
    }

    public static byte[] varIntToByteArray(long value) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream oos = new DataOutputStream(baos);
        Long l = value;
        try {
            if (l == l.byteValue()) {
                oos.writeByte(l.byteValue());
            } else if (l == l.shortValue()) {
                oos.writeShort(l.shortValue());
            } else if (l == l.intValue()) {
                oos.writeInt(l.intValue());
            } else if (l == l.longValue()) {
                oos.writeLong(l.longValue());
            } else if (l == l.floatValue()) {
                oos.writeFloat(l.floatValue());
            } else if (l == l.doubleValue()) {
                oos.writeDouble(l.doubleValue());
            }
        } catch (IOException e) {

        } finally {
            try {
                baos.close();
                oos.close();
            } catch (IOException e) {

            }
        }
        return baos.toByteArray();
    }

    /**
     * BASE64解密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        return Base64.getMimeDecoder().decode(key);
    }

    /**
     * BASE64加密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return Base64.getMimeEncoder().encodeToString(key);
    }
}